using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using tutFuelCellGame.Sharky3DCollisions;

namespace tutFuelCellGame
{
    public class Barrier : GameObject
    {
        public string BarrierType { get; set; }
        public bool Visible { get; set; }

        public Barrier(float scale)
            : base()
        {
            Visible = true;
            Scale = scale;
            BarrierType = null;
        }

        public void Reset()
        {
            Visible = true;
        }

        private Vector4[][] _modelBoundingPartSubdivisions =
            new Vector4[][]
                {
                    new Vector4[]
                        {
                            new Vector4(0.50f, 0.30f, 0.25f, 0.35f),
                            new Vector4(0.50f, 0.30f, 0.40f, 0.35f),
                            new Vector4(0.50f, 0.30f, 0.60f, 0.35f),
                            new Vector4(0.50f, 0.30f, 0.75f, 0.35f)
                        }
                };

        private Matrix[] _modelBoneTransforms;
        private BoundingPartList _modelBoundingParts;
        public BoundingPartList ModelBoundingParts
        {
            get { return _modelBoundingParts; }
        }

        private void BuildBoundingParts()
        {
            _modelBoundingParts = new BoundingPartList();

            BoundingPart boundingPart;
            int meshIndex = 0;

            foreach (ModelMesh mesh in Model.Meshes)
            {
                BoundingSphere[] pieces = new BoundingSphere[_modelBoundingPartSubdivisions[meshIndex].Length];
                int pieceIndex = 0;

                //Create, Scale and Position new BoundingSphere's according to the defined subdivisions for this part of the model.
                foreach (Vector4 subdivision in _modelBoundingPartSubdivisions[meshIndex])
                {
                    //Determine the new BoundingSphere's Radius
                    float radius = subdivision.W * mesh.BoundingSphere.Radius;

                    //Determine the new BoundingSphere's Center by interpolating. 
                    //The subdivision's X, Y, Z represent percentages in each axis. They will used across the full diameter of XNA's "default" BoundingSphere.
                    float x = MathHelper.Lerp(mesh.BoundingSphere.Center.X - mesh.BoundingSphere.Radius,
                                              mesh.BoundingSphere.Center.X + mesh.BoundingSphere.Radius, subdivision.X);
                    float y = MathHelper.Lerp(mesh.BoundingSphere.Center.Y - mesh.BoundingSphere.Radius,
                                              mesh.BoundingSphere.Center.Y + mesh.BoundingSphere.Radius, subdivision.Y);
                    float z = MathHelper.Lerp(mesh.BoundingSphere.Center.Z - mesh.BoundingSphere.Radius,
                                              mesh.BoundingSphere.Center.Z + mesh.BoundingSphere.Radius, subdivision.Z);

                    Vector3 centre = new Vector3(x, y, z);

                    pieces[pieceIndex] = new BoundingSphere(centre, radius);
                    pieceIndex++;
                }

                boundingPart = new BoundingPart(BoundingSphere, pieces,
                                                _modelBoneTransforms[mesh.ParentBone.Index], "barrier", Color.Cyan);

                _modelBoundingParts.Add(boundingPart);
                meshIndex++;
            }
        }

        public void Initialize(float boundingSphereFactor)
        {
            Position = Vector3.Down;
            BoundingSphere = CalculateBoundingSphere(boundingSphereFactor);

            _modelBoneTransforms = new Matrix[Model.Bones.Count];
            Model.CopyAbsoluteBoneTransformsTo(_modelBoneTransforms);
            BuildBoundingParts();

        }

        public Matrix GetWorldMatrix()
        {
            Matrix scaleMatrix = Matrix.CreateScale(Scale);
            Matrix translateMatrix = Matrix.CreateTranslation(Position);
            Matrix orientationMatrix = Matrix.CreateRotationY(Orientation);
            return orientationMatrix * scaleMatrix * translateMatrix;
        }

        public void Draw(Matrix view, Matrix projection, float barrierAlpha)
        {
            if (!Visible) return;

            Matrix worldMatrix = GetWorldMatrix();
            Alpha = barrierAlpha;
            DrawModelMeshes(worldMatrix, view, projection);
        }

        public void DrawShadow(Matrix view, Matrix projection, Matrix shadow)
        {
            if (!Visible) return;

            Matrix worldMatrix = GetWorldMatrix();
            DrawModelMeshesWithShadow(worldMatrix, view, projection, shadow);
        }

        public override void DrawBoundingSphere(Matrix view, Matrix projection, Model boundingSphereModel)
        {
            foreach (var part in _modelBoundingParts)
            {
                base.DrawBoundingSphere(view, projection, boundingSphereModel, part.ProximitySphereTransformed, Color.YellowGreen);
                foreach (var sphere in part.BoundingSpheresTransformed)
                    base.DrawBoundingSphere(view, projection, boundingSphereModel, sphere);
            }
        }

    }

}